<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <script>
        // var timer1 = null;
        // var timer2 = null;
        // var timer3 = null;
        // var timer4 = null;
        // var timer5 = null;

        // 闭包的特性 ： 


        // 是一个闭包 ：
        // 闭包 ： 一个函数 可以访问到外部的变量 ，那么 外部上下文环境对这个函数形成了包围。这个环境在内存里不会被销毁；
        // 闭包（closure）是一个函数以及其捆绑的周边环境状态（lexical environment，词法环境）的引用的组合。换而言之，闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中，闭包会随着函数的创建而被同时创建。
        
        // 全局变量不会被销毁
        // var a = 10;
        // function fn(){
        //     console.log(a);
        // }
        // fn();

        // 1.创建函数  2.调用函数  3.销毁函数内的一些变量；
        // function fn(){
        //     var a = 10;
        //     console.log(a);
        // }
        // fn();
        // console.log(a);


        // 常用闭包 一：
        // 占用内存；
        // function fn(){
        //     var a = 10;
        //     function fn2(){
        //         console.log(a);
        //     }
        //     return fn2;
        // }

        // var myfn = fn();
        // myfn();


        // 常用闭包二 ；
        // function fn(){
        //     var a = 10;
        //     return function(){
        //         console.log(a);
        //     }
        // }
        // var myfn = fn();
        // myfn();


        // 闭包的缓存特性；

        // 让下面的fn函数只执行一次 ；
        function fn(){
            console.log("需要执行的函数");
        }

        // 高阶函数 ：有函数作为输入或者是输出的函数被称为高阶函数；
        function execFn(fn){
            var flag = false ; // 代表fn是否执行了 ，false是fn没有执行 ；
            return function(){
                if(!flag){
                    fn();
                    flag = !flag;
                }else{
                    console.log("这个函数已经被执行过了");
                }
               
            } 
        }
        var myfn = execFn(fn);
        myfn();
        myfn();
        myfn();
        myfn();


        // 小练习 ： 把三元参数传成一元参数 （柯里化curry）

        function add(x,y,z){ // 三元函数  ，几元就是几个参数
            return x + y + z;
        }


        function curryFn(add){
            // ....
            return function(x){  // myadd 函数
                return function(y){
                    return function(z){
                        return add(x,y,z);
                    }
                }
            }
        }

        var myadd = curryFn(add);
        var res = myadd(1)(2)(3);  // 一元函数；
        console.log(res);





    </script>
</body>
</html>